namespace MLP.NeuralNet
{
	using System;

	[Serializable]
	public class Neuron: IVisual.I_Neuron
	{
		protected int		inputsCount = 1;
		protected float[]	weights = new float[1];	// gewischt der Synapsen
		protected float		threshold = 0.0f;
		protected IVisual.I_ActivationFunction	function = new SigmoidFunction();

		protected float		sum;		// gewichtete Eingabe
		protected float		output;		// Ausgabewert

		protected static Random	rand = new Random();

		// anzahl der Eingaben
		public int InputsCount
		{
			get { return inputsCount; }
			set
			{
				inputsCount = Math.Max(1, value);
				weights = new float[inputsCount];
			}
		}

		// Schwellenwert
		public float Threshold
		{
			get { return threshold; }
			set { threshold = value; }
		}

		// Activation function
		public IVisual.I_ActivationFunction ActivationFunction
		{
			get { return function; }
			set { function = value; }
		}

		// Augabewert
		public float Output
		{
			get { return output; }
		}

		// Get/Set gewichte
		public float this[int index]
		{
			get { return weights[index]; }
			set { weights[index] = value; }
		}

		public float Sum
		{
			get { return sum; }
		}


		public Neuron()
		{ }
		public Neuron(int inputs) : this(inputs, new SigmoidFunction())
		{ }
		public Neuron(int inputs, IVisual.I_ActivationFunction function)
		{
			this.function = function;
			InputsCount =  inputs;
		}

		// Ausgabe berechnen
		public float Compute(float[] input)
		{
			if (input.Length != inputsCount)
				throw new ArgumentException();

			sum = 0.0f;

			// gewichtete Summe berechnen
			for (int i = 0; i < inputsCount; i++)
			{
				sum += weights[i] * input[i];
				cls_Rechen_LOG.WRITE_LOG_LINE("\t\t\tCOMPUTE Gewicht i " + i + " => weights[i] * input[i] = " + weights[i] + " * " + input[i] + " = " + (weights[i] * input[i]) + "  sum = " + sum);
			}
			sum -= threshold;
			cls_Rechen_LOG.WRITE_LOG_LINE("\t\t\tsum -= threshold = " + sum);

			return (output = function.Output(sum));
		}

		public void Randomize()
		{
			for (int i = 0; i < inputsCount; i++)
				weights[i] = (float)(rand.NextDouble());

			threshold = (float)(rand.NextDouble());
		}
	}
}
